package com.qd.admin.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cdqidi.dto.ApiResult;
import com.cdqidi.dto.ApiResultWrapper;
import com.cdqidi.dto.DelDTO;
import com.cdqidi.util.page.PageUtil;
import com.cdqidi.valid.group.DefaultGroup;
import com.cdqidi.valid.group.UpdateGroup;
import com.qd.common.sys.annotation.DataScope;
import com.qd.common.sys.annotation.OperatorInfo;
import com.qd.common.sys.constant.Constants;
import com.qd.common.sys.domain.entity.org.OrgPersonDTO;
import com.qd.common.sys.domain.entity.org.OrgPersonsDTO;
import com.qd.common.sys.domain.entity.person.PersonDTO;
import com.qd.common.sys.domain.entity.person.PersonRoleDTO;
import com.qd.common.sys.domain.entity.person.PersonRolesDTO;
import com.qd.common.sys.enums.OperatorType;
import com.qd.system.service.person.AuthTokenService;
import com.qd.system.dto.PasswordDto;
import com.qd.system.service.person.PersonHoldService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 人员信息
 *
 * @author sjk
 */
@RestController
@Validated
@Slf4j
@RequiredArgsConstructor
public class PersonController {

    private final PersonHoldService personHoldService;
    private final AuthTokenService authTokenService;

    /**
     * 新增人员
     */
    @PreAuthorize("@ps.hasPermission('system:user:save')")
    @PostMapping(value = "/sys/sysPerson/save")
    @OperatorInfo(title = "添加人员档案", operator = OperatorType.INSERT)
    public ApiResultWrapper<Object> save(@Validated(DefaultGroup.class) @RequestBody PersonDTO personDTO) {
        if (!StringUtils.hasLength(personDTO.getPassword())) {
            personDTO.setPassword(Constants.DEFAULT_USER_PASSWORD);
        }
        if (null == personDTO.getAddTime()) {
            personDTO.setAddTime(LocalDateTime.now());
        }
        return personHoldService.savePerson(personDTO);
    }

    /**
     * 修改人员
     */
    @PreAuthorize("@ps.hasPermission('system:user:edit')")
    @PutMapping(value = "/sys/sysPerson/update")
    @OperatorInfo(title = "修改人员档案", operator = OperatorType.UPDATE)
    public ApiResultWrapper<Object> update(@Validated({UpdateGroup.class, DefaultGroup.class}) @RequestBody PersonDTO personDTO) {
        if (null == personDTO.getUpdateTime()) {
            personDTO.setUpdateTime(LocalDateTime.now());
        }
        return personHoldService.updatePerson(personDTO);
    }

    /**
     * 删除人员
     */
    @PreAuthorize("@ps.hasPermission('system:user:delete')")
    @DeleteMapping(value = "/sys/sysPerson/delete")
    @OperatorInfo(title = "删除人员档案", operator = OperatorType.DELETE)
    public ApiResultWrapper<Object> delete(@Validated @RequestBody DelDTO<String> delDTO) {
        final List<String> ids = delDTO.getIds();
        if (ids.size() == 1) {
            personHoldService.deleteByPersonId(ids.get(0));
        } else {
            personHoldService.deleteByPersonIds(ids);
        }

        return ApiResult.success("删除成功");
    }

    /**
     * 人员详情
     *
     * @return 列表
     */
    @GetMapping(value = "/sys/sysPerson/getById")
    public ApiResultWrapper<PersonDTO> getById(@Validated @NotBlank(message = "人员ID不能为空") String personId) {
        return personHoldService.getPersonAndRole(personId);
    }

    /**
     * 人员列表
     *
     * @param personDTO 查询参数
     * @return 列表
     */
    @GetMapping(value = "/sys/sysPerson/page")
    @DataScope(orgAlias = "p")
    public IPage<PersonDTO> page(PersonDTO personDTO) {
        return personHoldService.page(PageUtil.buildPage(personDTO), personDTO);
    }

    /**
     * 重置密码
     */
    @PreAuthorize("@ps.hasPermission('system:user:resetPassword')")
    @PutMapping(value = "/sys/sysPerson/resetPassword")
    @OperatorInfo(title = "重置人员密码", operator = OperatorType.UPDATE)
    public ApiResultWrapper<Object> resetPassword(@Validated @RequestBody Map<String, String> map) {
        final String personId = map.get("personId");
        final String password = map.get("password");
        final String confirmPassword = map.get("confirmPassword");
        if (!StringUtils.hasLength(personId)) {
            return ApiResult.error("用户ID不能为空");
        }
        if (!StringUtils.hasLength(password)) {
            return ApiResult.error("密码不能为空");
        }
        if (!StringUtils.hasLength(confirmPassword)) {
            return ApiResult.error("确认密码不能为空");
        }
        if (!password.equals(confirmPassword)) {
            return ApiResult.error("两次输入的密码不一致");
        }
        final PasswordDto passwordDto = new PasswordDto();
        passwordDto.setPersonId(personId);
        passwordDto.setPassword(password);
        passwordDto.setIsLoginUser(false);
        passwordDto.setIsCheckOldPassword(false);
        final ApiResultWrapper<Object> wrapper = personHoldService.resetPassword(passwordDto, true);
        if (wrapper.isSuccess()) {
            authTokenService.clearLoginCache(personId);
        }
        return wrapper;
    }

    /**
     * 设置组织机构
     */
    @PreAuthorize("@ps.hasPermission('system:person:setOrg')")
    @PostMapping(value = "/sys/sysPerson/setOrg")
    @OperatorInfo(title = "为人员设置组织机构信息", operator = OperatorType.INSERT)
    public ApiResultWrapper<Object> setOrg(@Validated @RequestBody OrgPersonsDTO orgPersonsDto) {
        return personHoldService.setOrg(personHoldService.buildOrgPersonList(orgPersonsDto));
    }

    /**
     * 设置角色
     */
    @PreAuthorize("@ps.hasPermission('system:user:setRole')")
    @PostMapping(value = "/sys/sysPerson/setRole")
    @OperatorInfo(title = "为人员设置角色", operator = OperatorType.INSERT)
    public ApiResultWrapper<Object> setRole(@RequestBody PersonRolesDTO personRolesDto) {
        final String personId = personRolesDto.getPersonId();
        if (!StringUtils.hasLength(personId)) {
            return ApiResult.error("用户ID不能为空");
        }
        return personHoldService.setRoles(personRolesDto);
    }

    /**
     * 人员信息导出
     *
     * @param query 查询参数
     */
    @PreAuthorize("@ps.hasPermission('system:user:export')")
    @GetMapping(value = "/sys/sysPerson/exportPerson")
    @OperatorInfo(title = "用户信息导出", operator = OperatorType.EXPORT)
    @DataScope(orgAlias = "p")
    public void exportPerson(PersonDTO query) {
        long startTime = System.currentTimeMillis();
        personHoldService.exportPerson(query);
        long endTime = System.currentTimeMillis();
        log.info("用户导出,总耗时: {}s", (endTime - startTime) / 1000);
    }

    /**
     * 人员和角色信息导出
     *
     * @param query 查询参数
     */
    @PreAuthorize("@ps.hasPermission('system:role:exportUser')")
    @GetMapping(value = "/sys/sysPerson/exportPersonRole")
    @OperatorInfo(title = "用户和角色信息导出", operator = OperatorType.EXPORT)
    public void exportPersonRole(PersonRoleDTO query) {
        long startTime = System.currentTimeMillis();
        personHoldService.exportPersonRole(query);
        long endTime = System.currentTimeMillis();
        log.info("用户和角色信息导出,总耗时: {}s", (endTime - startTime) / 1000);
    }

    /**
     * 人员和机构信息导出
     *
     * @param query 查询参数
     */
    @PreAuthorize("@ps.hasPermission('system:person:exportPersonOrg')")
    @GetMapping(value = "/sys/sysPerson/exportPersonOrg")
    @OperatorInfo(title = "人员和机构信息导出", operator = OperatorType.EXPORT)
    @DataScope(orgAlias = "p")
    public void exportPersonOrg(OrgPersonDTO query) {
        long startTime = System.currentTimeMillis();
        personHoldService.exportPersonOrg(query);
        long endTime = System.currentTimeMillis();
        log.info("人员和机构信息导出,总耗时: {}s", (endTime - startTime) / 1000);
    }

    /**
     * 删除机构和人员关系
     */
    @PreAuthorize("@ps.hasPermission('system:person:deleteOrgPerson')")
    @DeleteMapping(value = "/sys/sysPerson/deleteOrgPerson")
    @OperatorInfo(title = "删除机构和人员关系", operator = OperatorType.DELETE)
    public ApiResultWrapper<Object> deleteOrgPerson(@Validated @RequestBody DelDTO<String> delDTO) {
        final List<String> ids = delDTO.getIds();
        personHoldService.deleteOrgPerson(ids);
        return ApiResult.success();
    }
}
